package com.gis.utils;

import com.gis.properties.PostgresqlProperties;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.ArrayUtils;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.FeatureWriter;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.feature.AttributeTypeBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.gce.geotiff.GeoTiffReader;
import org.geotools.jdbc.JDBCDataStore;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;



@Component
@RequiredArgsConstructor
public class PostgresqlUtil {
    private final PostgresqlProperties postgresqlProperties;
    /**
     * @param file shp文件的位置
     * @return
     * @author
     * @description 倒入shp文件
     */
    public void importShpFileMethod(File file) {
        JDBCDataStore jdbcDataStore = connectPostgis();
        SimpleFeatureSource simpleFeatureSource = readSHP(file);
        JDBCDataStore ds = createShpTable(jdbcDataStore, simpleFeatureSource);
        writeShp2Postgis(ds, simpleFeatureSource);
    }

    /**
     * 链接到postgis
     *
     * @return
     */
    private JDBCDataStore connectPostgis() {
        JDBCDataStore jdbcDataStore = null;
        DataStore dataStore;
        Map<String, Object> params = new HashMap<>(16);
        params.put("dbtype", postgresqlProperties.getDbtype());
        params.put("host", postgresqlProperties.getHost());
        params.put("port", postgresqlProperties.getPort());
        params.put("schema", postgresqlProperties.getSchema());
        params.put("database", postgresqlProperties.getDatabase());
        params.put("user", postgresqlProperties.getUsername());
        params.put("passwd", postgresqlProperties.getPassword());

        try {
            dataStore = DataStoreFinder.getDataStore(params);
            if (dataStore != null) {
                jdbcDataStore = (JDBCDataStore) dataStore;
                System.out.println("链接数据库成功");
            } else {
                System.out.println("链接数据库失败");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return jdbcDataStore;
    }

    /**
     * 读取shp文件
     *
     * @param file
     * @return
     */
    private SimpleFeatureSource readSHP(File file) {
        //数据源
        SimpleFeatureSource simpleFeatureSource = null;
        try {
            //定义数据存储
            ShapefileDataStore shapefileDataStore = new ShapefileDataStore(file.toURI().toURL());
            //设置编码
            Charset charset = shapefileDataStore.getCharset();
            shapefileDataStore.setCharset(charset);
            String tableName = shapefileDataStore.getTypeNames()[0];
            //获取数据源
            simpleFeatureSource = shapefileDataStore.getFeatureSource(tableName);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return simpleFeatureSource;
    }

    /**
     * 读取tif栅格文件
     * @param file
     * @return
     * @throws IOException
     */
    private GridCoverage2D readRaster(File file) {
        GridCoverage2D raster = null;
        try {
            // 使用 GeoTiffReader 读取栅格数据
            GeoTiffReader reader = new GeoTiffReader(file);
            raster = reader.read(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return raster;
    }


    /**
     * 构造新SimpleFeatureType
     * @param simpleFeatureType
     * @return
     */
    private SimpleFeatureType convertToLowerCaseSchema(SimpleFeatureType simpleFeatureType) {
        // 创建一个新的 SimpleFeatureTypeBuilder
        SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();

        // 设置表名为小写
        builder.setName(simpleFeatureType.getName().toString().toLowerCase());
        builder.setCRS(simpleFeatureType.getCoordinateReferenceSystem());

        // 获取原始属性描述符
        List<AttributeDescriptor> oldAttributeDescriptors = simpleFeatureType.getAttributeDescriptors();

        // 新属性描述符列表
        List<AttributeDescriptor> newAttributeDescriptors = new ArrayList<>();

        for (AttributeDescriptor oldDescriptor : oldAttributeDescriptors) {
            // 创建属性构造器
            AttributeTypeBuilder typeBuilder = new AttributeTypeBuilder();
            typeBuilder.init(oldDescriptor.getType());
            typeBuilder.setNillable(true);

            // 设置字段名为小写
            String name = oldDescriptor.getLocalName().toLowerCase();
            typeBuilder.setName(name);

            // 创建新的属性描述符
            AttributeDescriptor newDescriptor = typeBuilder.buildDescriptor(name, oldDescriptor.getType());
            newAttributeDescriptors.add(newDescriptor);
        }

        // 添加新属性描述符到构造器
        builder.addAll(newAttributeDescriptors);

        // 构建新的 SimpleFeatureType
        return builder.buildFeatureType();
    }


    /**
     * 创建表
     */
    private JDBCDataStore createShpTable(JDBCDataStore jdbcDataStore, SimpleFeatureSource simpleFeatureSource) {
        SimpleFeatureType simpleFeatureType = simpleFeatureSource.getSchema();
        SimpleFeatureType lowerCaseFeatureType = convertToLowerCaseSchema(simpleFeatureType);
        try {
            String[] allTableNames = jdbcDataStore.getTypeNames();
            //如果存在,则先删除
            //这里根据需求决定是否删除表
            if (allTableNames != null && ArrayUtils.contains(allTableNames, simpleFeatureType.getTypeName())) {
                jdbcDataStore.removeSchema(simpleFeatureType.getTypeName());
            }
            //创建数据表
            jdbcDataStore.createSchema(lowerCaseFeatureType);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return jdbcDataStore;
    }

    /**
     * 把shp写入postgis
     *
     * @param jdbcDataStore
     * @param simpleFeatureSource
     */
    private void writeShp2Postgis(JDBCDataStore jdbcDataStore, SimpleFeatureSource simpleFeatureSource) {
        //获取模式
        SimpleFeatureType simpleFeatureType = simpleFeatureSource.getSchema();
        SimpleFeatureType lowerCaseFeatureType = convertToLowerCaseSchema(simpleFeatureType);
        FeatureWriter<SimpleFeatureType, SimpleFeature> writer = null;
        //开始写入数据
        try {
            //获取要素写入
            writer = jdbcDataStore.getFeatureWriter(lowerCaseFeatureType.getTypeName(), Transaction.AUTO_COMMIT);
            //获取数据源
            SimpleFeatureCollection simpleFeatureCollection = simpleFeatureSource.getFeatures();
            //获取要素遍历器
            SimpleFeatureIterator iterator = simpleFeatureCollection.features();
            while (iterator.hasNext()) {
                //写入下一个
                writer.hasNext();
                //要写入的空要素
                SimpleFeature writeNext = writer.next();
                //遍历获得的要素
                SimpleFeature simpleFeature = iterator.next();
                //赋值属性
                for (int i = 0; i < simpleFeature.getAttributeCount(); i++) {
                    writeNext.setAttribute(i, simpleFeature.getAttribute(i));
                }
                //写入
                writer.write();
            }
            System.out.println("导入成功");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            if (jdbcDataStore != null) {
                jdbcDataStore.dispose();
            }
        }
    }



//    raster2pgsql -s 4326 -I -C -M C:\Develop\WebGis\gis\gis-server\src\test\resources\20220114.tif -F -t 256x256 test | psql -h 192.168.92.131 -p 5432 -U postgres -d mmbdb -W

}
